<template>
    <div class="dialog-layout" :screen="fullScreen ? 'full' : ''">
        <div class="dialog-content" v-if="active" @scroll="onScroll($event)">
            <div class="dialog-close" @click="doClose()" v-if="canClose">
                <svg-icon name="dialog-close-full" v-if="fullScreen" />
                <svg-icon name="dialog-close-medium" v-else />
            </div>
            <div class="dialog-title" v-text="title" v-if="title"></div>
            <div class="dialog-body">
                <slot></slot>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: "Dialog",
    props: {
        visible: { type: [String, Number, Boolean, Object, Array], default: () => null },
        title: { type: String },
        canClose: { type: Boolean, default: true, },
        fullScreen: { type: Boolean, default: false, },
        beforeClose: { type: Function, default: () => null },
        beforeOpen: { type: Function, default: () => null },
    },
    data () {
        return {
            top: 0,
            left: 0,
            active: false,
        };
    },
    watch: {
        visible (newval, oldval) {
            this.setActive();
        },
    },
    methods: {

        getScrollWidth () {
            const scroll = document.createElement("div");
            const scrollIn = document.createElement("div");
            scroll.appendChild(scrollIn);
            scroll.style.width = "100px";
            scroll.style.height = "50px";
            scroll.style.overflow = "scroll";
            scroll.style.marginLeft = "-100000px";
            document.body.appendChild(scroll);
            const scrollInWidth = scrollIn.offsetWidth;
            const scrollWidth = scroll.offsetWidth;
            const tmp = setTimeout(() => {
                document.body.removeChild(scroll);
                clearTimeout(tmp);
            }, 10);
            return scrollWidth - scrollInWidth + 'px';
        },

        setActive () {
            const active = !!this.visible;
            // 展示时
            if (active == this.active) {
                // 相同不计算
            } else if (active) {
                this.onShow();
            } else {
                this.onClose();
            }
        },
        setScrollDisable () {

            const cache = window.DIALOGCACHE || { top: 0, left: 0, open: [] };
            const elems = document.body.querySelectorAll(':scope > .dialog-layout')

            if (elems.length <= 0) {
                // 关闭
                document.body.style.marginRight = '';
                document.body.style.height = '';

                window.DIALOGCACHE = cache;
                window.scrollTo(window.DIALOGCACHE.left, window.DIALOGCACHE.top);

            } else if (elems.length == 1) {
                // 打开
                cache.top = window.scrollY;
                cache.left = window.scrollX;
                window.DIALOGCACHE = cache;

                document.body.style.height = '100vh'
                document.body.style.marginRight = this.getScrollWidth();
                document.body.scrollTo(window.DIALOGCACHE.left, window.DIALOGCACHE.top);
            }


            // 这个方案太复杂了
            /*
            const cache = window.DIALOGCACHE || { top: 0, left: 0, open: [] };
            const oldopen = cache.open.length > 0;

            if (this.active) {
                cache.open = cache.open.filter(i => i != this._uid);
                cache.open.push(this._uid);
            } else {
                cache.open = cache.open.filter(i => i != this._uid);
            }

            const newopen = cache.open.length > 0;

            if (newopen == oldopen) {
                // 相同不管
            } else if (newopen) {
                // 打开
                const width = document.body.offsetWidth;
                const nuxt = document.getElementById('__nuxt')

                cache.top = window.scrollY;
                cache.left = window.scrollX;
                window.DIALOGCACHE = cache;

                nuxt.style.position = "fixed";
                nuxt.style.top = -window.DIALOGCACHE.top + "px";
                nuxt.style.left = -window.DIALOGCACHE.left + "px";
                nuxt.style.right = Math.max(0, document.body.offsetWidth - width) + 'px';

                document.body.style.overflow = 'hidden';

            } else {

                const nuxt = document.getElementById('__nuxt')
                // 关闭
                nuxt.style.position = "";
                nuxt.style.top = "";
                nuxt.style.left = "";
                nuxt.style.right = "";
                document.body.style.overflow = '';

                window.DIALOGCACHE = cache;
                window.scrollTo(window.DIALOGCACHE.left, window.DIALOGCACHE.top);
            }
            */
        },

        // 显示
        onShow () {
            if (!this.active) {
                document.body.appendChild(this.$el);
                this.active = true;
                this.$emit("show");
                this.$forceUpdate()
                setTimeout(() => {
                    this.$el.scrollTop = 0;
                    this.setScrollDisable()
                }, 0);
                setTimeout(() => this.active && this.$el.setAttribute('active', 'active'), 100);
            }
        },
        // 隐藏
        onClose () {
            if (this.active) {
                this.active = false;
                this.$emit("close");
                setTimeout(() => !this.active && this.$el.removeAttribute('active'), 0);
                setTimeout(() => {
                    // 防止点击过快
                    if (!this.active) {
                        this.$el.parentNode && this.$el.parentNode.removeChild(this.$el)
                        this.setScrollDisable()
                    }
                }, 500);
            }
        },

        // 关闭事件
        doClose () {
            if (this.beforeClose && typeof this.beforeClose == 'function') {
                const res = this.beforeClose()
                if (typeof res == 'boolean' && !res) {
                    // 明显的返回false，则拦截关闭事件
                } else {
                    this.onClose()
                }
            } else {
                this.onClose()
            }
        },
        // 滚动
        onScroll (event) {
            this.$emit("scroll", event);
        },
    },
    mounted () {
        this.setActive();
    },
    beforeDestroy () {
        this.onClose()
    },
};
</script>

<style lang="scss" scoped>
.dialog-layout {
    position: fixed;
    left: 0;
    top: 0;
    width: 100vw;
    height: 100vh;
    padding: 40px;
    box-sizing: border-box;
    pointer-events: none;
    z-index: 99;
    background: rgba(0, 0, 0, 0.7);
    opacity: 0;
    transition: opacity 0.5s;
    text-align: center;
    white-space: nowrap;
    overflow: auto;

    &::before {
        content: '';
        display: inline-block;
        width: 0;
        height: 100%;
        vertical-align: middle;
    }

    &[active] {
        opacity: 1;
        pointer-events: all;
    }

    &[screen='full'] {
        padding: 0;
        .dialog-content {
            border-radius: 0;
            width: 100vw;
            height: 100vh;
        }

        .dialog-close {
            position: absolute;
            right: 20px;
            top: 14px;
            width: 40px;
            height: 40px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            border-radius: 8px;
            color: #686868;
            transition: all 0.2s;
            svg {
                width: 18px;
                height: 18px;
            }
        }
    }
}

.dialog-content {
    display: inline-block;
    vertical-align: middle;
    position: relative;
    background: #fff;
    border-radius: 10px;
    white-space: normal;
    text-align: left;
    overflow: hidden;
}

.dialog-close {
    z-index: 1;
    position: absolute;
    right: 4px;
    top: 4px;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #555;
    transition: all 0.3s;
    cursor: pointer;
    border-radius: 4px;
    svg {
        width: 10px;
        height: 10px;
    }
    &:hover {
        background-color: rgba(255, 0, 0, 0.1);
        color: #8c1c14;
    }
}

.dialog-title {
    padding: 0 48px 0 48px;
    font-size: 14px;
    font-weight: bold;
    color: #000000;
    line-height: 40px;
    text-align: center;
    position: relative;
    text-align: center;
    &:before {
        content: '';
        position: absolute;
        left: 0;
        bottom: 0;
        right: 0;
        height: 1px;
        background-color: #e6e6e6;
    }
}

.dialog-body {
    flex: 1;
    overflow-y: overlay;
    overflow-x: hidden;
    width: 100%;
}
</style>
